#include "espWifiCfg.h"

EspWifiCfg::EspWifiCfg(const char* apSsid, const char* apPassword) : _apSsid(apSsid), _apPassword(apPassword), _server(80) {}

void EspWifiCfg::begin() {
    WiFi.mode(WIFI_AP);
    WiFi.softAP(_apSsid, _apPassword);

    // 启动 DNS 服务器，用于 Captive Portal
    _dnsServer.start(53, "*", WiFi.softAPIP());

    // 路由
    _server.on("/", std::bind(&EspWifiCfg::_handleRoot, this));
    _server.on("/wifilist", std::bind(&EspWifiCfg::_handleWifiList, this));
    _server.on("/connect", std::bind(&EspWifiCfg::_handleConnect, this));
    _server.onNotFound(std::bind(&EspWifiCfg::_handleNotFound, this));

    _server.begin();
    Serial.printf("AP started, SSID: %s, IP: %s\n", _apSsid, WiFi.softAPIP().toString().c_str());
}

void EspWifiCfg::loop() {
    _dnsServer.processNextRequest();
    _server.handleClient();
}

bool EspWifiCfg::updateWifiStatus(bool &wifiConnected, unsigned long &lastNTPAttempt) {
  bool changed = false;
  bool currentWifiStatus = (WiFi.status() == WL_CONNECTED);
    if (currentWifiStatus != wifiConnected) {
    wifiConnected = currentWifiStatus;
    changed = true;
    if (wifiConnected) {
      Serial.println("WiFi connected");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      lastNTPAttempt = millis() - 29000;  // trigger immediate NTP attempt
    } else {
      Serial.println("WiFi disconnected");
    }
  }
  return changed;
}

void EspWifiCfg::_handleRoot() {
    String html = R"rawliteral(
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>ESP32 WiFi 配网</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <style>
    body { background-color:#f8f9fa; }
    .container { margin-top: 40px; max-width: 400px; }
    .card { border-radius: 12px; box-shadow:0 4px 10px rgba(0,0,0,0.1); }
    #title { font-size: 1.6rem; font-weight: 600; text-align: center; margin-bottom: 20px; }
    .ssid-item { 
      cursor: pointer; 
      font-size: 1.2rem; 
      text-decoration: underline; 
      padding: 12px; 
    }
    .ssid-item:hover { background-color:#e9ecef; }
    .btn-refresh { 
      height: 48px; 
      padding: 0 25px; 
      margin-top: 20px; 
      display: block;
      margin-left: auto;
      margin-right: auto;
    }
    #wifiPage, #pwdPage, #resultPage { display:none; }
    .wifi-name { font-size: 1.3rem; font-weight: 600; text-align: center; margin-bottom: 15px; }
    #pwd { 
      display: block; 
      margin: 0 auto 25px auto; 
      width: 80%; 
      height: 50px; 
      font-size: 1.2rem; 
      text-align: center;
    }
    .btn-row {
      display: flex;
      justify-content: center;
      gap: 15px;
    }
    .btn-row button {
      min-width: 100px;
      height: 45px;
    }
    .result-icon { 
      font-size: 4rem; 
      text-align: center; 
      margin: 20px 0; 
    }
    .success { color: #28a745; }
    .error { color: #dc3545; }
    .connecting { color: #ffc107; }
    .result-message { 
      font-size: 1.2rem; 
      text-align: center; 
      margin-bottom: 25px; 
      white-space: pre-line;
    }
  </style>
</head>
<body>
<div class="container">
  <div class="card">
    <div class="card-body d-flex flex-column" style="min-height:400px">

      <!-- WiFi列表页 -->
      <div id="wifiPage" class="d-flex flex-column flex-grow-1">
        <div id="title">搜索网络，请等待...</div>
        <ul class="list-group flex-grow-1" id="wifiList"></ul>
        <button class="btn btn-primary btn-refresh" onclick="loadWifiList()">刷新</button>
      </div>

      <!-- 密码输入页 -->
      <div id="pwdPage">
        <div class="wifi-name">输入WiFi密码</div>
        <div class="wifi-name" id="ssidText"></div>
        <form onsubmit="event.preventDefault(); connectWifi();">
          <input type="password" class="form-control" id="pwd" placeholder="请输入密码">
          <div class="btn-row">
            <button type="submit" class="btn btn-success">连接</button>
            <button type="button" class="btn btn-secondary" onclick="backToWifiList()">返回</button>
          </div>
        </form>
      </div>

      <!-- 连接结果页 -->
      <div id="resultPage" class="d-flex flex-column justify-content-center flex-grow-1">
        <div class="result-icon connecting" id="resultIcon">⏳</div>
        <div class="result-message" id="resultMessage">正在连接...</div>
        <div class="btn-row" id="resultButtons">
          <button type="button" class="btn btn-primary" onclick="backToWifiList()" id="backButton">返回列表</button>
          <button type="button" class="btn btn-success" onclick="closePage()" id="closeButton" style="display:none;">完成</button>
        </div>
      </div>

    </div>
  </div>
</div>

<script>
let selectedSsid = '';

function showPage(page){
  document.getElementById('wifiPage').style.display = (page==='wifi')?'block':'none';
  document.getElementById('pwdPage').style.display  = (page==='pwd')?'block':'none';
  document.getElementById('resultPage').style.display = (page==='result')?'block':'none';
}

function loadWifiList(){
  document.getElementById('title').innerText = "搜索网络，请等待...";
  document.getElementById('wifiList').innerHTML = "";

  fetch('/wifilist').then(r=>r.json()).then(list=>{
    let html='';
    list.forEach(w=>{
      const safeSsid = w.ssid.replace(/'/g, "&#39;").replace(/"/g, "&quot;");
      html += `<li class="list-group-item ssid-item" onclick="selectWifi('${safeSsid}')">${w.ssid}</li>`;
    });
    document.getElementById('wifiList').innerHTML = html;
    document.getElementById('title').innerText = "选择WiFi网络";
  }).catch(err=>{
    document.getElementById('title').innerText = "搜索失败，请重试";
  });
}

function selectWifi(ssid){
  selectedSsid = ssid;
  document.getElementById('ssidText').innerText = ssid;
  document.getElementById('pwd').value = '';
  showPage('pwd');
}

function backToWifiList(){
  showPage('wifi');
  loadWifiList();
}

function showConnecting(){
  const icon = document.getElementById('resultIcon');
  const msg = document.getElementById('resultMessage');
  const backBtn = document.getElementById('backButton');
  const closeBtn = document.getElementById('closeButton');
  
  icon.className = 'result-icon connecting';
  icon.innerHTML = '⏳';
  msg.innerText = '正在连接 ' + selectedSsid + '...';
  backBtn.style.display = 'block';
  closeBtn.style.display = 'none';
  showPage('result');
}

function showFinalResult(success, message){
  const icon = document.getElementById('resultIcon');
  const msg = document.getElementById('resultMessage');
  const backBtn = document.getElementById('backButton');
  const closeBtn = document.getElementById('closeButton');
  
  if(success){
    icon.className = 'result-icon success';
    icon.innerHTML = '✓';
    msg.innerText = message;
    backBtn.style.display = 'none';
    closeBtn.style.display = 'block';
  } else {
    icon.className = 'result-icon error';
    icon.innerHTML = '✗';
    msg.innerText = message;
    backBtn.style.display = 'block';
    closeBtn.style.display = 'none';
  }
}

function closePage() {
  alert('配网完成！您可以关闭此页面。');
}

function connectWifi(){
  const pwd = document.getElementById('pwd').value;
  
  if(!pwd){
    alert('请输入WiFi密码');
    return;
  }
  
  showConnecting();
  
  // 设置超时时间
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), 25000);
  
  fetch(`/connect?ssid=${encodeURIComponent(selectedSsid)}&pwd=${encodeURIComponent(pwd)}`, {
    signal: controller.signal
  })
  .then(response => {
    clearTimeout(timeoutId);
    if (!response.ok) {
      throw new Error(`HTTP错误: ${response.status}`);
    }
    return response.text();
  })
  .then(message => {
    console.log('服务器返回:', message);
    
    // 直接使用服务器返回的消息，不进行前端判断
    // 后端会返回明确的状态标识
    if (message.startsWith('SUCCESS:')) {
      showFinalResult(true, message.substring(8)); // 去掉"SUCCESS:"前缀
    } else if (message.startsWith('ERROR:')) {
      showFinalResult(false, message.substring(6)); // 去掉"ERROR:"前缀
    } else {
      // 兼容旧格式
      if (message.includes('成功') || message.includes('IP地址')) {
        showFinalResult(true, message);
      } else {
        showFinalResult(false, message);
      }
    }
  })
  .catch(error => {
    clearTimeout(timeoutId);
    console.error('请求错误:', error);
    
    if (error.name === 'AbortError') {
      showFinalResult(false, '连接超时，请重试');
    } else {
      showFinalResult(false, '网络错误，请检查连接后重试');
    }
  });
}

showPage('wifi');
loadWifiList();
</script>
</body>
</html>
)rawliteral";
    _server.send(200, "text/html", html);
}

void EspWifiCfg::_handleWifiList() {
    int n = WiFi.scanNetworks();
    String json = "[";
    for (int i = 0; i < n; i++) {
        if (i > 0) json += ",";
        json += "{\"ssid\":\"" + WiFi.SSID(i) + "\",\"rssi\":" + String(WiFi.RSSI(i)) + "}";
    }
    json += "]";
    _server.send(200, "application/json", json);
}

void EspWifiCfg::_handleConnect() {
    String ssid = _server.arg("ssid");
    String pwd = _server.arg("pwd");

  Serial.printf("Begin connect: SSID=%s\n", ssid.c_str());

    if (ssid.isEmpty()) {
        _server.send(200, "text/plain", "ERROR:缺少SSID参数");
        return;
    }

    // 保持AP+STA模式，确保Web服务器在连接过程中可用
    WiFi.mode(WIFI_AP_STA);
    WiFi.softAP(_apSsid, _apPassword);
    WiFi.begin(ssid.c_str(), pwd.c_str());

  Serial.printf("Connecting to: %s\n", ssid.c_str());

    // 等待连接完成，同时处理Web请求
    unsigned long start = millis();
    int lastStatus = WiFi.status();
    bool connectionInProgress = true;

    while (connectionInProgress && millis() - start < 20000) {
        delay(500);

        int currentStatus = WiFi.status();
    if (currentStatus != lastStatus) {
      Serial.printf("WiFi status changed: %d -> %d\n", lastStatus, currentStatus);
      lastStatus = currentStatus;
    }

        // 检查连接状态
        if (currentStatus == WL_CONNECTED) {
            connectionInProgress = false;
        } else if (currentStatus == WL_CONNECT_FAILED) {
            connectionInProgress = false;
        } else if (millis() - start >= 15000) {
            // 超时检查：15秒后如果还在连接中，可能是密码错误
            connectionInProgress = false;
        }

        _server.handleClient();  // 处理客户端请求
        _dnsServer.processNextRequest();
    }

    // 根据实际连接状态返回明确的结果
  if (WiFi.status() == WL_CONNECTED) {
    String successMsg = "SUCCESS:WiFi connected!\n\nSSID: " + ssid + "\nIP: " + WiFi.localIP().toString();
    _server.send(200, "text/plain", successMsg);
    Serial.printf("\n✓ Connected! IP: %s\n", WiFi.localIP().toString().c_str());
  } else if (WiFi.status() == WL_CONNECT_FAILED) {
    // Connection failed - most likely wrong password
    String errorMsg = "ERROR: Wrong password!\n\nPlease check the WiFi password and try again.";
    _server.send(200, "text/plain", errorMsg);
    Serial.println("\n✗ Connection failed, possible wrong password");

    // restore AP mode
    WiFi.mode(WIFI_AP);
    WiFi.softAP(_apSsid, _apPassword);
  } else {
    // Timeout or other error
    String errorMsg = "ERROR: Connection timed out!\n\nPlease check:\n• WiFi password\n• Signal strength\n• Router status";
    _server.send(200, "text/plain", errorMsg);
    Serial.println("\n✗ Connection timed out");

    // restore AP mode
    WiFi.mode(WIFI_AP);
    WiFi.softAP(_apSsid, _apPassword);
  }
}

void EspWifiCfg::_handleNotFound() {
    _server.sendHeader("Location", "/", true);
    _server.send(302, "text/plain", "");
}